package minjre.libparse;


import minjre.utils.CommandUtils;
import minjre.utils.FileUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

/**
 * @description:
 * @author: 陈瑞东
 * @create: 2021-05-28 16:35
 */
public class LibParse {

    private Map<String, JarFile> jarMap;
    private File destFile;
    private File transTo;

    public LibParse(String outPath) {
        this.jarMap = new HashMap<>();
        this.destFile = new File("./lib-out");
        transTo = new File(outPath);
    }

    /**
     * 开始解析
     */
    public void runParse(String runJar, String javaSrc){
        StringBuffer buffer = CommandUtils.doCommand("GBK", true,javaSrc, "-jar", "-verbose:class", runJar);
        System.out.println(buffer);
        String[] classArr = buffer.toString().split("\n");
        for (String line : classArr) {
            String[] lineData = null;
            if((lineData = parseLine(line)) != null){
                copyClass(lineData);
            }
        }
        for (File file : destFile.listFiles()) {
            jarPackage(file);
        }
        FileUtils.delete(destFile);
    }

    /**
     * 将复制出来的文件打成jar包
     */
    private void jarPackage(File file) {
        File libFile = new File(transTo, "lib");
        if(!libFile.exists()){
            libFile.mkdirs();
        }
        List<String> commandList = new ArrayList<>();
        commandList.add("jar");
        commandList.add("-cvf");
        // 生成的jar文件路径
        commandList.add(libFile.getPath() + "/" + file.getName() + ".jar");
        commandList.add("-C");
        // class文件路径
        commandList.add(destFile.getPath() + "/" + file.getName() + "/");
        commandList.add(".");
        CommandUtils.doCommand("GBK", false,commandList.toArray(new String[0]));
    }

    /**
     * 复制 类文件
     * @param lineData
     */
    private void copyClass(String[] lineData) {
        try {
            // 类名
            String className = lineData[0];
            // jar包位置
            String jarSrc = lineData[1];
            // jar包文件名
            String parentJarName = lineData[2];
            JarFile jarFile;
            if(jarMap.containsKey(jarSrc)){
                jarFile = jarMap.get(jarSrc);
            }else{
                jarFile = new JarFile(jarSrc);
                jarMap.put(jarSrc, jarFile);
            }
            ZipEntry classZip = jarFile.getEntry(className);
            InputStream in = jarFile.getInputStream(classZip);
            File dest = new File(destFile,parentJarName + "/" + className);
            FileUtils.mkdirParentIfUnExist(dest);
            FileUtils.copyFile(in, dest);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解析一行数据
     * @param line
     */
    private String[] parseLine(String line) {
        if(!line.trim().startsWith("[Loaded")){
            return null;
        }

        String[] lineSplit = line.split("from");
        String className = lineSplit[0].split(" ")[1].replace(".","/") + ".class";
        String jarSrc = lineSplit[1].trim().substring(0, lineSplit[1].trim().length() - 1);
        // 如果没有该jar文件则返回null
        File file = new File(jarSrc);
        if(!file.exists()){
            return null;
        }
        String parentJarName = file.getName().substring(0, file.getName().length() - ".jar".length());
        return new String[]{className, jarSrc, parentJarName};
    }
}
